#define LOG_TAG    "wifi"

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>

#include "project_common.h"

#define DEFAULT_SCAN_LIST_SIZE      50
// #define DEFAULT_SCAN_TIME_MIN       0
// #define DEFAULT_SCAN_TIME_MAX       100
#define MAX_SCAN_DATA_SIZE      (512*1024)/*默认的iw wlan0 scan指令返回值size*/

// #define EXAMPLE_ESP_MAXIMUM_RETRY   5

#define WIFI_CONNECTED_BIT (1<<0)
#define WIFI_FAIL_BIT      (1<<1)
#define WIFI_STA_START_BIT (1<<2)

typedef struct {
    uint8_t bssid[6];                     /**< MAC address of AP */
    uint8_t ssid[33];                     /**< SSID of AP */
    int8_t  rssi;                         /**< signal strength of AP */
    uint8_t primary;                      /**< channel of AP */
    uint8_t authmode[20];                 /**< authmode of AP */
} wifi_ap_record_t;

wifi_ap_record_t ap_info[DEFAULT_SCAN_LIST_SIZE];
uint16_t ap_count = 0;

//static int s_retry_num = 0;
static volatile int is_connect_ap = false;//是否已经连接上ap了

//替代事件组的条件变量
static pthread_mutex_t wifi_mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t wifi_cond = PTHREAD_COND_INITIALIZER;
static volatile int wifi_cond_bits = 0;

//通知app_wifi_task执行相应的动作
typedef enum {
    APP_WIFI_MSG_NONE,
    APP_WIFI_MSG_SWITCH_STA,
    APP_WIFI_MSG_SWITCH_AP,
} app_wifi_msg_t;
struct wifi_msg {
    long mtype;
    app_wifi_msg_t msg;
};
#define MSG_TYPE  20
static volatile int msgid;

//发送信号给app_wifi_task
static void app_wifi_msg_send_to_task(app_wifi_msg_t msg);
//设置ap模式
static void app_wifi_ap_set(const char *ssid, const char *password, const char *authmode, bool isHidden);
//设置sta模式
static void app_wifi_sta_set(const char *ssid, const char *password, const char *authmode);
//关闭自动重连，暂时用这个替代吧
//#define DISABLE_WIFI_AUTO_CONN() app_wifi_sta_set("ASDLS,D&,T", "8", "psk2")
#define app_wifi_dis_auto_conn() app_wifi_ap_set("ASDLS", "88888888", "psk2", true)

static volatile int64_t app_wifi_sysset_tick = 0;//“wifi”命令执行时候的时标
#define APP_WIFI_SYSSET_DELAY_MS   1000/*执行”wifi“命令后，需要阻塞的时间*/
//更新 “wifi”命令执行时候的时标
static void app_wifi_sysset_tick_update(void);
//根据 “wifi”命令执行时候的时标 执行相应的延时。最大APP_WIFI_SYSSET_DELAY_MS
static void app_wifi_sysset_delay(void);

//打印AP列表
static void app_wifi_print_scan(const wifi_ap_record_t *ap_info, uint8_t print_idx)
{
    USER_UART_INFO("AP:%d,%s,%d,%s,%d,%02x:%02x:%02x:%02x:%02x:%02x\n",
        print_idx,ap_info[print_idx].ssid,ap_info[print_idx].primary,
        ap_info[print_idx].authmode,ap_info[print_idx].rssi,
        ap_info[print_idx].bssid[0],ap_info[print_idx].bssid[01],ap_info[print_idx].bssid[2],
        ap_info[print_idx].bssid[3],ap_info[print_idx].bssid[4],ap_info[print_idx].bssid[5]
    );
}
static void str_cpy(uint8_t *dest, uint8_t *src, uint8_t numb)
{
    uint8_t *r = src,*w = dest, n = 0;
    for (n = 0; n < numb; ++n)
    {
        if ( (*r == '\r') || (*r == '\n') || (*r == '\0') || (n == (numb-1)) ) {
            *w = '\0';
            break;
        }
        else {
            *w = *r;
        }
        w++;r++;
    }
}
#define PEER_READ           400
#define CHECK_BUFF_MAX      1024
//从"iw wlan0 scan"命令的返回值中，读取AP列表
static int find_ap_list(FILE *fp, wifi_ap_record_t *record, uint8_t num_max)
{
    char buff[CHECK_BUFF_MAX];
    int read_idx = 0;
    int tail_idx = 0;
    int read_numb = 0,curr=0, per;
    char *pairwise_ciphers_str=NULL;//加密方式分别存放在两个位置，需要在后面拼接起来

    read_idx = tail_idx = 0;
    //读取一部分数据出来判断
    per = fread(&buff[tail_idx], 1, PEER_READ, fp);
    tail_idx += per;
//    printf("read_idx=%d, tail_idx=%d\n", read_idx, tail_idx);
    for (read_idx = 0; read_idx < tail_idx; ++read_idx)
    {
        //补充数据 防止后续判断中只匹配到了字符串，而丢掉了后面的数据
        if ( (tail_idx-read_idx) == (PEER_READ/2)  ) {
            int num = tail_idx-read_idx;
            memcpy(buff, &buff[read_idx], num);//位移数据到缓冲区头部
            read_idx = 0;
            tail_idx = num;

            per = fread(&buff[tail_idx], 1, PEER_READ, fp);
            if (per > 0) {
//                printf("\ntail_idx %d add %d!!!!\n", tail_idx, per);
                tail_idx += per;
            }
        }
//            printf("%c", buff[read_idx]);

        if ( memcmp(&buff[read_idx], "BSS", strlen("BSS") ) == 0 )
        {
            //printf("***bssid:%s\n", &buff[read_idx+4]);
            curr = read_numb;
            if (read_numb >= num_max) {
                break;
            }
            //从字符串中提取出uint8_t型mac地址数组
            char *endptr;
            record[curr].bssid[0] = (uint8_t)strtol(&buff[read_idx+4], &endptr, 16);
            record[curr].bssid[1] = (uint8_t)strtol(&buff[read_idx+7], &endptr, 16);
            record[curr].bssid[2] = (uint8_t)strtol(&buff[read_idx+10], &endptr, 16);
            record[curr].bssid[3] = (uint8_t)strtol(&buff[read_idx+13], &endptr, 16);
            record[curr].bssid[4] = (uint8_t)strtol(&buff[read_idx+16], &endptr, 16);
            record[curr].bssid[5] = (uint8_t)strtol(&buff[read_idx+19], &endptr, 16);
//printf("%d:bssid:%x:%x:%x:%x:%x:%x\n", read_numb, record[curr].bssid[0], record[curr].bssid[1], record[curr].bssid[2], record[curr].bssid[3], record[curr].bssid[4], record[curr].bssid[5]);
            pairwise_ciphers_str = NULL;//更新
            ++read_numb;
        }
        if ( memcmp(&buff[read_idx], "signal:", strlen("signal:") ) == 0 )
        {
            record[curr].rssi = atoi(&buff[read_idx+7]);
//                printf("rssi:%d\n", record[curr].rssi);
        }
        if ( memcmp(&buff[read_idx], "SSID: ", strlen("SSID: ") ) == 0 )
        {
            str_cpy(record[curr].ssid, (uint8_t *)&buff[read_idx+6], sizeof(record[curr].ssid));
//            printf("ssid:%s\n", record[curr].ssid);
        }
        if ( memcmp(&buff[read_idx], "* Pairwise ciphers:", strlen("* Pairwise ciphers:") ) == 0 )
        {
            pairwise_ciphers_str = &buff[read_idx+20];//记录第一段加密方式
        }
        if ( memcmp(&buff[read_idx], "* Authentication suites:", strlen("* Authentication suites:") ) == 0 )
        {
            size_t len = 0;
            str_cpy(record[curr].authmode, (uint8_t *)&buff[read_idx+25], sizeof(record[curr].authmode));
            //补上一个空格
            len = strlen((char*)record[curr].authmode);
            if (len < (sizeof(record[curr].authmode)-1)) {
                record[curr].authmode[len] = ' ';
                record[curr].authmode[++len] = '\0';
            }
            if (pairwise_ciphers_str != NULL) {
                str_cpy(&record[curr].authmode[len], (uint8_t *)pairwise_ciphers_str, sizeof(record[curr].authmode)-len);
            }
//                printf("auth:%s\n", record[curr].authmode);
        }
        if ( memcmp(&buff[read_idx], "* primary channel: ", strlen("* primary channel: ") ) == 0 )
        {
            record[curr].primary = atoi(&buff[read_idx+18]);
//                printf("primary:%d\n", record[curr].primary);
        }
    }

//    printf("\nscan over!!\n");
    return read_numb;
}

//更新 “wifi”命令执行时候的时标
static void app_wifi_sysset_tick_update(void)
{
    app_wifi_sysset_tick = Hal_GetTick();
}
//根据 “wifi”命令执行时候的时标 执行相应的延时。最大APP_WIFI_SYSSET_DELAY_MS
static void app_wifi_sysset_delay(void)
{
    uint32_t tick_offset;
    uint32_t tick_his = app_wifi_sysset_tick;
    int64_t  tick_curr = Hal_GetTick();

    if ( (tick_his+APP_WIFI_SYSSET_DELAY_MS) > tick_curr )
    {
        tick_offset = (tick_his+APP_WIFI_SYSSET_DELAY_MS) - tick_curr;
        usleep(tick_offset*1000);
        log_d("system set need delay %ld ms", tick_offset);
    }
}

/* set scan method */
void app_wifi_scan(int argc, char** argv)
{
    if (argv[0] != NULL) {//打印命令描述
        log_i("%s", argv[0]);
    }
    memset(ap_info, 0, sizeof(ap_info));

    //根据 “wifi”命令执行时候的时标 执行相应的延时。最大APP_WIFI_SYSSET_DELAY_MS
    app_wifi_sysset_delay();

    FILE *fp;
    fp = popen("iw wlan0 scan", "r+");//触发scan

    //fp实际上是一个pipe文件描述符,无法使用fseek(),这里用scan_fp作为备份
    FILE *scan_fp = NULL;
    ssize_t rlen;
    scan_fp = fopen("/tmp/upass_scan_data", "w+");

    char *buff = (char *) malloc(MAX_SCAN_DATA_SIZE);
    memset(buff, 0, MAX_SCAN_DATA_SIZE);
    rlen = fread(buff, 1, MAX_SCAN_DATA_SIZE, fp);
    if (rlen <= 0) {
        log_d("app_wifi_scan() : rlen == 0");
        pclose(fp);
        pclose(scan_fp);
        free(buff);
        USER_UART_INFO("[ATWS] ERROR:2\n");//scan无数据
        return;
    }
//    log_d("iw+ scan len=%d str= %s", rlen, buff);
    //当处于sta状态时候，scan会偶然出现前者提示
    //当在执行”wifi“指令后，没有足够的delay会产生后者提示
    if ( (strstr(buff, "command failed: Resource busy") != NULL) ||
         (strstr(buff, "--debug         enable netlink debugging") != NULL) )
    {
        pclose(fp);
        pclose(scan_fp);
        free(buff);
        USER_UART_INFO("[ATWS] ERROR:1\n");//系统忙
        return;
    }
    //原本的find_ap_list()使用的参数是FILE *类型，这里就懒得改了，将buff的内容保存进scan_fp就好
    fwrite(buff, 1, rlen, scan_fp);
    fseek(scan_fp, 0, SEEK_SET);
    ap_count = find_ap_list(scan_fp, ap_info, DEFAULT_SCAN_LIST_SIZE);//提取数据

    log_i("Total APs scanned = %u", ap_count);
    if (ap_count > 0) {
        for (int i = 0; i < ap_count; i++) {
            app_wifi_print_scan(ap_info,i);
        }
    }
    pclose(fp);
    pclose(scan_fp);
    free(buff);
    USER_UART_INFO("[ATWS] OK\n");
}

// 在Event task内调用的事件处理函数
// static void event_handler(void* arg, esp_event_base_t event_base,
//                                 int32_t event_id, void* event_data)
// {
//     if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
//         xEventGroupSetBits(s_wifi_event_group, WIFI_STA_START_BIT);//通知：sta初始化结束（暂时没用到）
//     } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
//         if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
//             esp_wifi_connect();
//             s_retry_num++;
//             ESP_LOGI(TAG, "retry to connect to the AP");
//         } else {
//             xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);//通知：连接AP失败
//         }
//         ESP_LOGI(TAG,"connect to the AP fail");
//     } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
//         ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
//         ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
//         s_retry_num = 0;
//         xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);//通知：连接AP成功
//     }
// }

//从ATWS指令中获取到的对应SSID的加密模式
static bool wifi_get_authmode(const char **read_mod, const char * ssid)
{
    uint8_t i;
    log_i("numb %d:get_authmode ssid=%s" ,ap_count, ssid);
    if (read_mod != NULL && ssid != NULL) {
        log_d("read_mod=0x%x" , (int)read_mod);
        for (i = 0; i < ap_count; ++i)
        {
            log_d("ssid=%s" ,ap_info[i].ssid);
            if (memcmp(ap_info[i].ssid, ssid, strlen((char*)ssid)) == 0)
            {
                // none 表示不加密
                // psk 表示WPA-PSK模式
                // psk2 表示WPA-PSK2模式
                // psk-mixed 表示WPA-PSK & WPA-PSK2 & Auto
                // psk-mixed+ccmp 表示WPA-PSK & WPA-PSK2 & AES
                // psk-mixed+tkip 表示WPA-PSK & WPA-PSK2 & TKIP
                // psk-mixed+tkip+ccmp 表示WPA-PSK & WPA-PSK2 & TKIP & AES
                *read_mod = "psk-mixed";//暂时不做判断，统一按照有密码的处理
                return true;
            }
        }
    }
    else {
        return false;
    }
    return false;
}

// ATPN指令对应处理函数
void app_wifi_sta_connect(int argc, char** argv)
{
    if (argv[0] != NULL) {//打印命令描述
        log_i("%s", argv[0]);
    }
    if ( (argv[1]==NULL)||(argv[2]==NULL)||(strlen(argv[2])<8) )
    {
        USER_UART_INFO("[ATPN] ERROR:2\n");//参数错误
        return;
    }

    const char *ssid=argv[1], *password=argv[2];
    const char *authmode = NULL;
    if (wifi_get_authmode(&authmode, ssid) != false)
    {
        //设置sta
        app_wifi_sta_set(ssid, password, authmode);

        log_i("wifi_init_sta finished.");

        //通知app_wifi_task开始连接ap
        app_wifi_msg_send_to_task(APP_WIFI_MSG_SWITCH_STA);

        //使用条件变量替代esp32的事件组接收信息
        /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
        * number of re-tries (WIFI_FAIL_BIT). The bits are set by app_wifi_task() */
        if (pthread_mutex_lock(&wifi_mtx) != 0)
        {
            log_e("error pthread_mutex_lock");
            exit(-1);
        }
        while ( !((wifi_cond_bits&WIFI_CONNECTED_BIT) ||
                (wifi_cond_bits&WIFI_FAIL_BIT)) )
        {
            log_d("waitup");
            if (pthread_cond_wait(&wifi_cond, &wifi_mtx) != 0)
            {
                log_e("error pthread_cond_wait");
                exit(-1);
            }
        }
        log_d("cond is true in thread:%ld", (long)pthread_self());
        if (wifi_cond_bits&WIFI_CONNECTED_BIT) {
            log_i("connected to ap SSID:%s password:%s",
                    ssid, password);
            USER_UART_INFO("[ATPN] OK\n");
            is_connect_ap = true;//已经连接上AP了
            wifi_cond_bits &= ~WIFI_CONNECTED_BIT;
        }
        if (wifi_cond_bits&WIFI_FAIL_BIT) {
            log_i("Failed to connect to SSID:%s, password:%s",
                    ssid, password);
            USER_UART_INFO("[ATPN] ERROR:3\n");//连接AP失败
            wifi_cond_bits &= ~WIFI_FAIL_BIT;
        }
        if (pthread_mutex_unlock(&wifi_mtx) != 0)
        {
            log_e("error pthread_mutex_unlock");
            exit(-1);
        }
    }
    else
    {
        USER_UART_INFO("[ATPN] ERROR:5\n");//无ap信息
    }
}

//是否连接上ap了
bool app_wifi_is_connect_ap(void)
{
    return (is_connect_ap != false);
}

//发送信号给app_wifi_task
static void app_wifi_msg_send_to_task(app_wifi_msg_t msg)
{
    struct wifi_msg msg_buff;
    msg_buff.msg = msg;
    msg_buff.mtype = MSG_TYPE;
    msgsnd(msgid, &msg_buff, sizeof(app_wifi_msg_t), 0);
}
//app_wifi_task发送信号给订阅者
static void app_wifi_flag_pubilish(int bits)
{
    if (pthread_mutex_lock(&wifi_mtx) != 0)
    {
        log_e("error pthread_mutex_lock");
        exit(-1);
    }
    wifi_cond_bits |= bits;
    if (pthread_mutex_unlock(&wifi_mtx) != 0)
    {
        log_e("error pthread_mutex_unlock");
        exit(-1);
    }
    pthread_cond_signal(&wifi_cond);
    //pthread_cond_broadcast(&wifi_cond);
}
//检查是否连上WIFI
static bool app_wifi_sta_check_connect(void)
{
    FILE *fp;
    char buff[1024];
    bool ret = false;

    fp = popen("iw wlan0 link", "r+");
    int len = fread(buff, 1, sizeof(buff), fp);
    if ( (len > 0) && (strstr(buff, "Connected to") != NULL)){
        ret = true;
    }
    pclose(fp);
    return ret;
}
//检查是否分配IP
static bool app_wifi_sta_check_ip(uint8_t ipv4_addr[4])
{
    FILE *fp;
    char buff[1024];
    char *pRead = NULL;
    bool ret = false;

    //正常返回带有括号内的字符串 <"address": "192.168.2.252",>
    fp = popen("ubus call network.interface.wwan status | grep \"address\"", "r+");
    int len = fread(buff, 1, sizeof(buff), fp);
    if (len > 0)
    {
        //log_d("app_wifi_sta_check_ip = %s", buff);
        //暂时不考虑ipv6的情况
        if ( (pRead=strstr(buff, "\"address\": \"")) != NULL )
        {
            // //test
            // char src[] = "\"addresses\",\n\"address\": \"192.168.2.252\",";
            // char target[] = "\"address\": \"";
            // char *read = strstr(src, target);
            // log_i("src = %s\n", src);
            // log_i("target = %s\n", target);
            // if (read) {
            //     log_i("strstr = %s\n", read);
            // }

            if (ipv4_addr != NULL)
            {
                ipv4_addr[0] = (uint8_t)strtol(&pRead[12], &pRead, 10);//&buff[12]指向ip字符串首地址
                ipv4_addr[1] = (uint8_t)strtol(&pRead[1], &pRead, 10);
                ipv4_addr[2] = (uint8_t)strtol(&pRead[1], &pRead, 10);
                ipv4_addr[3] = (uint8_t)strtol(&pRead[1], &pRead, 10);
                log_d("get ip = %d.%d.%d.%d", ipv4_addr[0], ipv4_addr[1], ipv4_addr[2], ipv4_addr[3]);
            }
            ret = true;
        }
    }
    pclose(fp);
    return ret;
}


// //使能WIFI硬件
// static void app_wifi_enable(void)
// {
//     char uci_str[20];
//     //判断wifi是否关闭，是则打开。
//     int ret = cuci_get("wireless.@wifi-device[0].disabled", uci_str, sizeof(uci_str));
//     log_d("wireless.@wifi-device[0].disabled=0x%x, ret=%d",uci_str[0], ret);
//     if ( ((ret == UCI_OK) && (uci_str[0]=='0')) ||
//           (ret == UCI_ERR_NOTFOUND) ) 
//     {
//         cuci_set("wireless.@wifi-device[0].disabled", "0");
//         system("wifi");//更新wifi参数
//     }
// }

/**
* @brief 设置ap模式
* @param[in] ssid:需要连接的ap ssid
* @param[in] password:对应ap的密码
* @param[in] authmode:加密方式,有"none" "psk" "psk2" "psk-mixed"等(暂时不支持"none",并且当前只测试了"psk-mix")
* @param[in] isHidden:是否启用匿名ssid
*/
static void app_wifi_ap_set(const char *ssid, const char *password, const char *authmode, bool isHidden)
{
    if ( (ssid==NULL) || (password==NULL) || (authmode==NULL) ) {
        log_e("app_wifi_ap_set() argument error");
    }
    //开启无线
    cuci_set("wireless.@wifi-device[0].disabled", "0");
    //配置network
    cuci_set("network.wwan", "interface");
    cuci_set("network.wwan.proto", "dhcp");
    //配置wireless
    cuci_set("wireless.default_radio0.network", "wwan");
    cuci_set("wireless.default_radio0.mode", "ap");
    cuci_set("wireless.default_radio0.ssid", ssid);
    cuci_set("wireless.default_radio0.encryption", authmode);
    cuci_set("wireless.default_radio0.key", password);
    if (isHidden) {
        cuci_set("wireless.default_radio0.hidden", "1");
    }
    else {
        cuci_set("wireless.default_radio0.hidden", "0");
    }
    //配置firewall
    cuci_add_list("firewall.@zone[1].network", "wwan");

    system("wifi");
    //system("/etc/init.d/network restart");//这条指令的执行速度过慢，用“wifi”指令取代
    system("/etc/init.d/firewall restart");
    //sleep(1);
    //更新 “wifi”命令执行时候的时标
    app_wifi_sysset_tick_update();
}


/**
* @brief 设置sta模式
* @param[in] ssid:需要连接的ap ssid
* @param[in] password:对应ap的密码
* @param[in] authmode:加密方式,有"none" "psk" "psk2" "psk-mixed"等(暂时不支持"none",并且当前只测试了"psk-mix")
*/
static void app_wifi_sta_set(const char *ssid, const char *password, const char *authmode)
{
    if ( (ssid==NULL) || (password==NULL) || (authmode==NULL) ) {
        log_e("app_wifi_sta_set() argument error");
    }
    //开启无线
    cuci_set("wireless.@wifi-device[0].disabled", "0");
    //配置network
    cuci_set("network.wwan", "interface");
    cuci_set("network.wwan.proto", "dhcp");
    //配置wireless
    cuci_set("wireless.default_radio0.network", "wwan");
    cuci_set("wireless.default_radio0.mode", "sta");
    cuci_set("wireless.default_radio0.ssid", ssid);
    cuci_set("wireless.default_radio0.encryption", authmode);
    cuci_set("wireless.default_radio0.key", password);
    //配置firewall
    cuci_add_list("firewall.@zone[1].network", "wwan");

    system("wifi");
    //system("/etc/init.d/network restart");//这条指令的执行速度过慢，用“wifi”指令取代
    system("/etc/init.d/firewall restart");
    //sleep(1);
    //更新 “wifi”命令执行时候的时标
    app_wifi_sysset_tick_update();
}

typedef enum  {
    APP_WIFI_TASK_S_IDLE,
    APP_WIFI_TASK_S_STA_DISCONN,//断开链接
    APP_WIFI_TASK_S_STA_WAI_IP,//等待分配IP
    APP_WIFI_TASK_S_STA_CONN,//已经链接
} app_wifi_task_state_t;

//WIFI任务
void *app_wifi_task(void *arg)
{
    (void)arg;
    struct wifi_msg msg_buff;
    app_wifi_task_state_t app_wifi_task_state;
	int64_t tick_total, tick_inr/*interval*/;

    while (1)
    {
        usleep(10*1000);
        app_wifi_msg_t rcv_msg = APP_WIFI_MSG_NONE;
        if (0 < msgrcv(msgid, &msg_buff, sizeof(app_wifi_msg_t), MSG_TYPE, IPC_NOWAIT))
        {
            rcv_msg = msg_buff.msg;
            log_d("app_wifi_task rev msg = %d", (int)rcv_msg);
        }
        switch (app_wifi_task_state)
        {
            case APP_WIFI_TASK_S_IDLE:
            if (rcv_msg == APP_WIFI_MSG_SWITCH_STA)
            {
                tick_total = Hal_GetTick();
                tick_inr = tick_total;
                app_wifi_task_state = APP_WIFI_TASK_S_STA_DISCONN;
            }
            break;

            case APP_WIFI_TASK_S_STA_DISCONN:
            if (rcv_msg == APP_WIFI_MSG_SWITCH_STA)
            {
                tick_total = Hal_GetTick();
                tick_inr = tick_total;
                break;
            }
            else if (Hal_IsTicksTimeout(tick_total, 30*1000L))//30秒没连上
            {
                //关闭自动重连
                app_wifi_dis_auto_conn();
                app_wifi_flag_pubilish(WIFI_FAIL_BIT);
                app_wifi_task_state = APP_WIFI_TASK_S_IDLE;

                log_i("connect to the AP fail");
                break;
            }
            //周期性检查
            else if (Hal_IsTicksTimeout(tick_inr, 250))
            {
                tick_inr = Hal_GetTick();
                if (app_wifi_sta_check_connect())//连上
                {
                    app_wifi_task_state = APP_WIFI_TASK_S_STA_WAI_IP;
                    break;
                }
                log_d("retry to connect to the AP");
            }
            break;

            case APP_WIFI_TASK_S_STA_WAI_IP:
            if (rcv_msg == APP_WIFI_MSG_SWITCH_STA)
            {
                tick_total = Hal_GetTick();
                tick_inr = tick_total;
                app_wifi_task_state = APP_WIFI_TASK_S_STA_DISCONN;
                break;
            }
            else if (Hal_IsTicksTimeout(tick_total, 30*1000L))//30秒没连上
            {
                //关闭自动重连
                app_wifi_dis_auto_conn();
                app_wifi_flag_pubilish(WIFI_FAIL_BIT);
                app_wifi_task_state = APP_WIFI_TASK_S_IDLE;

                log_i("connect to the AP fail");
                break;
            }
            //周期性检查
            else if (Hal_IsTicksTimeout(tick_inr, 250))
            {
                uint8_t ipv4_addr[4];
                tick_inr = Hal_GetTick();
                if (app_wifi_sta_check_ip(ipv4_addr))//分配IP
                {
                    log_d("get ip sucess");
                    app_wifi_task_state = APP_WIFI_TASK_S_STA_CONN;
                    app_wifi_flag_pubilish(WIFI_CONNECTED_BIT);
                    break;
                }
                log_d("retry to check is get ip");
            }
            break;

            case APP_WIFI_TASK_S_STA_CONN:
            if (rcv_msg == APP_WIFI_MSG_SWITCH_STA)
            {
                tick_total = Hal_GetTick();
                tick_inr = tick_total;
                app_wifi_task_state = APP_WIFI_TASK_S_STA_DISCONN;
                break;
            }
            //周期性检查
            else if (Hal_IsTicksTimeout(tick_inr, 250))
            {
                tick_inr = Hal_GetTick();
                if (!app_wifi_sta_check_connect())//断开
                {
                    tick_total = Hal_GetTick();
                    tick_inr = tick_total;
                    app_wifi_task_state = APP_WIFI_TASK_S_STA_DISCONN;//自动重连
                    app_wifi_flag_pubilish(WIFI_FAIL_BIT);
                    break;
                }
            }
            break;
        }
    }
}

//WIFI相关功能的初始化
void app_wifi_init(void)
{
    pthread_t wifi_id;

    //app_wifi_enable();
    //关闭自动重连
    app_wifi_dis_auto_conn();

    //初始化system-v 队列 当前的openwrt不支持posix mq
    msgid = msgget(IPC_PRIVATE, S_IRUSR | S_IWUSR);//0600
    if (msgid == -1) {
        log_e("msgget fail = %s", strerror(errno));
        exit(-1);
    }
    pthread_create(&wifi_id, NULL, app_wifi_task, NULL);

    // app_wifi_scan();
    // app_wifi_sta_connect((uint8_t*)"casa", (uint8_t*)"12345678");//用来测试的AP热点：casa
    // app_socket_client_connect((uint8_t*)"192.168.2.140", (uint8_t*)"3333");//用来测试的tcp server
}

